#include "Ast.h"
#include "SymbolTable.h"
#include "Unit.h"
#include "Instruction.h"
#include "IRBuilder.h"
#include <string>
#include "Type.h"
#include <iostream>
#include <assert.h>

extern FILE* yyout;
int Node::counter = 0;
IRBuilder* Node::builder = nullptr;
Type* nowret;
bool in_while=false;
bool and_or=false;
int br_need=0;
extern Unit unit;

Node::Node() {
    seq = counter++;
    next = nullptr;
}

void Node::setNext(Node* node) {
    Node* n = this;
    while (n->getNext()) {
        n = n->getNext();
    }
    if (n == this) {
        this->next = node;
    } else {
        n->setNext(node);
    }
}

//讲某个指令集合中的跳转指令全部设置分支到固定的basic block
void Node::backPatch(std::vector<Instruction*> &list, BasicBlock*bb)
{
    for(auto &inst:list)
    {
        if(inst->isCond())
            dynamic_cast<CondBrInstruction*>(inst)->setTrueBranch(bb);
        else if(inst->isUncond())
            dynamic_cast<UncondBrInstruction*>(inst)->setBranch(bb);
    }
}

Operand* Node::type_cast(Type* targetType, Operand* operand) {
    if(targetType==operand->getType()){
        return operand;
    }
    BasicBlock *bb = builder->getInsertBB();
    Function *func = bb->getParent();
    Operand* tar_operand = new Operand(new TemporarySymbolEntry(targetType, SymbolTable::getLabel()));
    Operand* temp = new Operand(new TemporarySymbolEntry(TypeSystem::boolType, SymbolTable::getLabel()));
    if(operand->getType()->isBool() && targetType->isInt()) {
        //printf("666\n");
        new ZextInstruction(tar_operand,operand, bb);
    }
    else if(operand->getType()->isInt()&&targetType->isBool()){
        new CmpInstruction(CmpInstruction::NE, tar_operand,operand,new Operand(new ConstantSymbolEntry(TypeSystem::intType, 0)),bb);
    }
    return tar_operand;
}

//将两个指令序列合并
std::vector<Instruction*> Node::merge(std::vector<Instruction*> &list1, std::vector<Instruction*> &list2)
{
    std::vector<Instruction*> res(list1);
    res.insert(res.end(), list2.begin(), list2.end());
    return res;
}

void Ast::output() {
    fprintf(yyout, "program\n");
    //printf("program\n");
    if (root != nullptr)
        root->output(4);
}

void ExprNode::output(int level) {
    std::string name, type;
    name = symbolEntry->toStr();
    type = symbolEntry->getType()->toStr();
    fprintf(yyout, "%*cconst string\ttype:%s\t%s\n", level, ' ', type.c_str(),
            name.c_str());
    //printf("%*cconst string\ttype:%s\t%s\n", level, ' ', type.c_str(),
            //name.c_str());
}

BinaryExpr::BinaryExpr(SymbolEntry* se,int op,ExprNode* expr1,ExprNode* expr2)
    : ExprNode(se), op(op), expr1(expr1), expr2(expr2) {
    dst = new Operand(se);
    
    //类型检查添加
    if (expr1->getType()->isVoid() || expr2->getType()->isVoid()) {
        fprintf(stderr,
                "invalid operand of type \'void\' to binary \'opeartor \'\n");
    }
    //如果是关系运算，那么就
    if (op >= BinaryExpr::AND && op <= BinaryExpr::NOTEQUAL) {
        type = TypeSystem::boolType;
        
    } else
        type = TypeSystem::intType;
};

void BinaryExpr::output(int level) {
    std::string op_str;
    switch (op) {
        case ADD:
            op_str = "add";
            break;
        case SUB:
            op_str = "sub";
            break;
        case MUL:
            op_str = "mul";
            break;
        case DIV:
            op_str = "div";
            break;
        case MOD:
            op_str = "mod";
            break;
        case AND:
            op_str = "and";
            break;
        case OR:
            op_str = "or";
            break;
        case LESS:
            op_str = "less";
            break;
        case LESSEQUAL:
            op_str = "lessequal";
            break;
        case GREATER:
            op_str = "greater";
            break;
        case GREATEREQUAL:
            op_str = "greaterequal";
            break;
        case EQUAL:
            op_str = "equal";
            break;
        case NOTEQUAL:
            op_str = "notequal";
            break;
    }
    fprintf(yyout, "%*cBinaryExpr\top: %s\n", level, ' ', op_str.c_str());
    expr1->output(level + 4);
    expr2->output(level + 4);
}

int BinaryExpr::getValue() {
    int value;
    switch (op) {
        case ADD:
            value = expr1->getValue() + expr2->getValue();
            break;
        case SUB:
            value = expr1->getValue() - expr2->getValue();
            break;
        case MUL:
            value = expr1->getValue() * expr2->getValue();
            break;
        case DIV:
            value = expr1->getValue() / expr2->getValue();
            break;
        case MOD:
            value = expr1->getValue() % expr2->getValue();
            break;
        case AND:
            value = expr1->getValue() && expr2->getValue();
            break;
        case OR:
            value = expr1->getValue() || expr2->getValue();
            break;
        case LESS:
            value = expr1->getValue() < expr2->getValue();
            break;
        case LESSEQUAL:
            value = expr1->getValue() <= expr2->getValue();
            break;
        case GREATER:
            value = expr1->getValue() > expr2->getValue();
            break;
        case GREATEREQUAL:
            value = expr1->getValue() >= expr2->getValue();
            break;
        case EQUAL:
            value = expr1->getValue() == expr2->getValue();
            break;
        case NOTEQUAL:
            value = expr1->getValue() != expr2->getValue();
            break;
    }
    return value;
}
UnaryExpr::UnaryExpr(SymbolEntry* se, int op, ExprNode* expr)
    : ExprNode(se, UNARYEXPR), op(op), expr(expr) {
    std::string op_str = op == UnaryExpr::NOT ? "!" : "-";
    if(op==UnaryExpr::NOT){
        op_str="+";
    }
    //加入类型错误检查，判断进行一元运算的表达式是否为void
    if (expr->getSymbolEntry()->getType()->isVoid()) {
        fprintf(stderr,
                "invalid operand of type \'void\' to unary \'opeartor%s\'\n",
                op_str.c_str());
        assert(!(expr->getType()->isVoid()));
    }
    type = TypeSystem::intType;
    dst = new Operand(se);
};
void UnaryExpr::output(int level) {
    std::string op_str;
    switch (op) {
        case NOT:
            op_str = "not";
            break;
        case SUB:
            op_str = "minus";
            break;
    }
    fprintf(yyout, "%*cUnaryExpr\top: %s\n", level, ' ', op_str.c_str());
    //printf("%*cUnaryExpr\top: %s\n", level, ' ', op_str.c_str());
    expr->output(level + 4);
}

int UnaryExpr::getValue() {
    int value;
    switch (op) {
        case NOT:
            value = !(expr->getValue());
            break;
        case SUB:
            value = -(expr->getValue());
            break;
    }
    return value;
}

void CallExpr::output(int level) {
    std::string name, type;
    int scope;
    name = symbolEntry->toStr();
    type = symbolEntry->getType()->toStr();
    scope = dynamic_cast<IdentifierSymbolEntry*>(symbolEntry)->getScope();
    fprintf(yyout, "%*cCallExpr\tfunction name: %s\tscope: %d\ttype: %s\n",
            level, ' ', name.c_str(), scope, type.c_str());
    //printf("%*cCallExpr\tfunction name: %s\tscope: %d\ttype: %s\n",
            //level, ' ', name.c_str(), scope, type.c_str());
    Node* temp = param;
    while (temp) {
        temp->output(level + 4);
        temp = temp->getNext();
    }
}
CallExpr::CallExpr(SymbolEntry* se, ExprNode* param)
    : ExprNode(se), param(param) {
    dst = nullptr;
    if (symbolEntry) {
        Type* type = symbolEntry->getType();
        this->type = ((FunctionType*)type)->getRetType();
        if (this->type != TypeSystem::voidType) {
            SymbolEntry* se = new TemporarySymbolEntry(this->type, SymbolTable::getLabel());
            dst = new Operand(se);
        }
    }
    if (((IdentifierSymbolEntry*)se)->isSysf()) {
        unit.insertDeclare(se);
    }
    is_single=true;
}
void Constant::output(int level) {
    std::string type, value;
    type = symbolEntry->getType()->toStr();
    value = symbolEntry->toStr();
    fprintf(yyout, "%*cIntegerLiteral\tvalue: %s\ttype: %s\n", level, ' ',
            value.c_str(), type.c_str());
    //printf("%*cIntegerLiteral\tvalue: %s\ttype: %s\n", level, ' ',
            //value.c_str(), type.c_str());
}

int Constant::getValue() {
    // assert(symbolEntry->getType()->isInt());
    return ((ConstantSymbolEntry*)symbolEntry)->getValue();
}



int Id::getValue() {
    // assert(symbolEntry->getType()->isInt());
    return ((IdentifierSymbolEntry*)symbolEntry)->getValue();
}

Id::Id(SymbolEntry *se, ExprNode *arrIdx): ExprNode(se), arrIdx(arrIdx){
    if (se) {
        type = se->getType();
        if (type->isInt()) {
            SymbolEntry* temp = new TemporarySymbolEntry(TypeSystem::intType, SymbolTable::getLabel());
            dst = new Operand(temp);
        }
    }
    is_single=true;
}

void Id::output(int level)
{
    
    std::string name, type;
    int scope;
    name = symbolEntry->toStr();
    type = symbolEntry->getType()->toStr();
    scope = dynamic_cast<IdentifierSymbolEntry*>(symbolEntry)->getScope();
    fprintf(yyout, "%*cId\tname: %s\tscope: %d\ttype: %s\n", level, ' ',
            name.c_str(), scope, type.c_str());
    //printf("%*cId\tname: %s\tscope: %d\ttype: %s\n", level, ' ',
            //name.c_str(), scope, type.c_str());
    if (arrIdx) {
        ExprNode* temp = arrIdx;
        int i = 0;
        while (temp) {
            temp->output(level + 4 + 4 * i++);
            temp = (ExprNode*)(temp->getNext());
        }
    }
}

void CompoundStmt::output(int level) {
    fprintf(yyout, "%*cCompoundStmt\n", level, ' ');
    //printf("%*cCompoundStmt\n", level, ' ');
    if (stmt)
        stmt->output(level + 4);
}

void SeqNode::output(int level) {
    // fprintf(yyout, "%*cSequence\n", level, ' ');
    stmt1->output(level);
    stmt2->output(level);
}

void DeclStmt::output(int level) {
    fprintf(yyout, "%*cDeclStmt\n", level, ' ');
   // printf("%*cDeclStmt\n", level, ' ');
    id->output(level + 4);
    if (expr)
        expr->output(level + 4);
    if (this->getNext()) {
        this->getNext()->output(level);
    }
}

void BlankStmt::output(int level) {
    fprintf(yyout, "%*cBlankStmt\n", level, ' ');
    //printf("%*cBlankStmt\n", level, ' ');
}

void IfStmt::output(int level) {
    fprintf(yyout, "%*cIfStmt\n", level, ' ');
    //printf("%*cIfStmt\n", level, ' ');
    cond->output(level + 4);
    thenStmt->output(level + 4);
}

void IfElseStmt::output(int level) {
    fprintf(yyout, "%*cIfElseStmt\n", level, ' ');
    //printf("%*cIfElseStmt\n", level, ' ');
    cond->output(level + 4);
    thenStmt->output(level + 4);
    elseStmt->output(level + 4);
}

void WhileStmt::output(int level) {
    fprintf(yyout, "%*cWhileStmt\n", level, ' ');
    //printf("%*cWhileStmt\n", level, ' ');
    cond->output(level + 4);
    stmt->output(level + 4);
}
void BreakStmt::output(int level) {
    fprintf(yyout, "%*cBreakStmt\n", level, ' ');
    //printf("%*cBreakStmt\n", level, ' ');
}

void ContinueStmt::output(int level) {
    fprintf(yyout, "%*cContinueStmt\n", level, ' ');
    //printf("%*cContinueStmt\n", level, ' ');
}

void ReturnStmt::output(int level) {
    fprintf(yyout, "%*cReturnStmt\n", level, ' ');
    //printf("%*cReturnStmt\n", level, ' ');
    if (retValue != nullptr)
        retValue->output(level + 4);
}

AssignStmt::AssignStmt(ExprNode* lval, ExprNode* expr)
    : lval(lval), expr(expr) {
        //检查赋值类型和左值类型
    Type* type = ((Id*)lval)->getType();
    SymbolEntry* se = lval->getSymbolEntry();
    bool flag = true;
    if (type->isInt()) {
        if (((IntType*)type)->isConst()) {
            fprintf(stderr,
                    "cannot assign to variable \'%s\' with const-qualified "
                    "type \'%s\'\n",
                    ((IdentifierSymbolEntry*)se)->toStr().c_str(),
                    type->toStr().c_str());
            flag = false;
        }
    } 
    if (flag && !expr->getType()->isInt()) {
        fprintf(stderr,
                "cannot initialize a variable of type \'int\' with an rvalue "
                "of type \'%s\'\n",
                expr->getType()->toStr().c_str());
    }
}

void AssignStmt::output(int level) {
    fprintf(yyout, "%*cAssignStmt\n", level, ' ');
    //printf("%*cAssignStmt\n", level, ' ');
    lval->output(level + 4);
    expr->output(level + 4);
}

void ExprStmt::output(int level) {
    fprintf(yyout, "%*cExprStmt\n", level, ' ');
    //printf("%*cExprStmt\n", level, ' ');
    expr->output(level + 4);
}

void FunctionDef::output(int level) {
    std::string name, type;
    name = se->toStr();
    type = se->getType()->toStr();
    fprintf(yyout, "%*cFunctionDefine\tfunction name: %s\ttype: %s\n", level,
            ' ', name.c_str(), type.c_str());
    //printf("%*cFunctionDefine\tfunction name: %s\ttype: %s\n", level,
            //' ', name.c_str(), type.c_str());
    if (decl) {
        decl->output(level + 4);
    }
    stmt->output(level + 4);
}


//下面是类型检查的代码
bool Ast::typeCheck(Type* t)
{
    if(root != nullptr)
        root->typeCheck(t);
    return false;
}
bool FunctionDef::typeCheck(Type* retType) {
    SymbolEntry* se = this->getSymbolEntry();
    Type* ret = ((FunctionType*)(se->getType()))->getRetType();
    StmtNode* stmt = this->stmt;
    if (stmt == nullptr) {
        if (ret != TypeSystem::voidType)
            fprintf(stderr, "non-void function does not return a value\n");
        return false;
    }
    if (!stmt->typeCheck(ret)) {
        if(ret != TypeSystem::voidType){
            fprintf(stderr, "function does not have a return statement\n");
            assert(stmt->typeCheck(ret));
        }
        return false;
    }
    return false;
}
bool BinaryExpr::typeCheck(Type* retType) {
    return false;
}

bool UnaryExpr::typeCheck(Type* t){
    return false;
}

bool CallExpr::typeCheck(Type* t){
    return false;
}

bool ExprStmt::typeCheck(Type* t){
    return false;
}

bool Constant::typeCheck(Type* retType) {
    return false;
}

bool Id::typeCheck(Type* retType) {
    return false;
}

bool IfStmt::typeCheck(Type* retType) {
    if (thenStmt)
        return thenStmt->typeCheck(retType);
    return false;
}

bool IfElseStmt::typeCheck(Type* retType) {
    bool flag1 = false, flag2 = false;
    if (thenStmt)
        flag1 = thenStmt->typeCheck(retType);
    if (elseStmt)
        flag2 = elseStmt->typeCheck(retType);
    return flag1 || flag2;
}

bool CompoundStmt::typeCheck(Type* retType) {
    if (stmt)
        return stmt->typeCheck(retType);
    return false;
}

bool SeqNode::typeCheck(Type* retType) {
    bool flag1 = false, flag2 = false;
    if (stmt1)
        flag1 = stmt1->typeCheck(retType);
    if (stmt2)
        flag2 = stmt2->typeCheck(retType);
    return flag1 || flag2;
}

bool DeclStmt::typeCheck(Type* retType) {
    return false;
}

bool ReturnStmt::typeCheck(Type* retType) {
    if (!retType) {
        fprintf(stderr, "expected unqualified-id\n");
        assert(retType);
        return true;
    }
    if (!retValue && !retType->isVoid()) {
        fprintf(
            stderr,
            "return-statement with no value, in function returning \'%s\'\n",
            retType->toStr().c_str());
            assert(retValue || retType->isVoid());
        return true;
    }
    
    if (retValue && retType->isVoid()) {
        fprintf(
            stderr,
            "return-statement with a value, in function returning \'void\'\n");
        assert(!retValue || !retType->isVoid());
        return true;
    }

    if (!retValue || !retValue->getSymbolEntry()){
        assert(retValue && retValue->getSymbolEntry());
        return true;
    }
        
    if (retType->isFunc()&&((FunctionType*)retType)->getRetType()->isVoid()){
        fprintf(
            stderr,
            "return-statement with a void function\n");
        assert(!retType->isFunc()||!((FunctionType*)retType)->getRetType()->isVoid());
        return true;
    }
    Type* type = retValue->getType();
    if (type != retType) {
        fprintf(stderr,
                "cannot initialize return object of type \'%s\' with an rvalue "
                "of type \'%s\'\n",
                retType->toStr().c_str(), type->toStr().c_str());
    }
    return true;
}

bool AssignStmt::typeCheck(Type* retType) {
    return false;
}
bool WhileStmt::typeCheck(Type* retType){
    if (stmt){
        bool res=stmt->typeCheck(retType);
        return res;
    }
    return false;
}
bool ContinueStmt::typeCheck(Type* retType) {
    return false;
}
bool BreakStmt::typeCheck(Type* retType) {
    return false;
}






//下面是中间代码生成的编码

//总的代码生成需要unit来作为整个编译单元
void Ast::genCode(Unit *unit)
{
    IRBuilder *builder = new IRBuilder(unit);
    Node::setIRBuilder(builder);
    //printf("begin to gen code \n");
    if(root==nullptr)
        printf("empty root!\n");
    root->genCode();
}
//生成函数代码时，需要首先得到将函数添加到哪个编译单元去
void FunctionDef::genCode()
{
    std::string name, type;
    //name = se->toStr();
    //type = se->getType()->toStr();
    //std::cout<<name<<std::endl;
    Unit *unit = builder->getUnit();
    //创建函数结构，并将其插入unit，初始化一个basic block作为entry
    Function *func = new Function(unit, se);
    BasicBlock *entry = func->getEntry();
    nowret=((FunctionType*)(this->getSymbolEntry()))->getRetType();
    //将该函数的entry作为正在处理的单元
    br_need=0;
    builder->setInsertBB(entry);
    if(decl)
        decl->genCode();
    if(stmt)
        stmt->genCode();

    /**
     * Construct control flow graph. You need do set successors and predecessors for each basic block.
     * Todo
    */
   for (auto block = func->begin(); block != func->end(); block++) {
        //获取该块的最后一条指令
        Instruction* it = (*block)->begin();
        Instruction* last = (*block)->rbegin();
        while (it != last) {
            if (it->isCond() || it->isUncond()) {
                (*block)->remove(it);
                //printf("remove\n");
            }
            it = it->getNext();
        }
        if (last->isCond()) {
            BasicBlock *tb, *fb;
            tb =((CondBrInstruction*)(last))->getTrueBranch();
            fb =((CondBrInstruction*)(last))->getFalseBranch();
        //if we have ret value the tb or fb is not empty
            if (tb->empty()) {
                //printf("tb add\n");
                new RetInstruction(nullptr, tb);

            } else if (fb->empty()) {
                //printf("fb add\n");
                new RetInstruction(nullptr, fb);
            }
            (*block)->addSucc(tb);
            (*block)->addSucc(fb);
            tb->addPred(*block);
            fb->addPred(*block);
        }
        else if (last->isUncond())  //无条件跳转指令可获取跳转的目标块
        {
            BasicBlock* dst =((UncondBrInstruction*)(last))->getBranch();
            (*block)->addSucc(dst);
            dst->addPred(*block);
            if (dst->empty()) {
                if (((FunctionType*)(se->getType()))->getRetType() ==TypeSystem::intType)
                    new RetInstruction(new Operand(new ConstantSymbolEntry(TypeSystem::intType, 0)),dst);
                else if (((FunctionType*)(se->getType()))->getRetType() ==TypeSystem::voidType)
                    new RetInstruction(nullptr, dst);
            }
        }
        //最后一条语句不是返回以及跳转
        else if (!last->isRet()) {
            if (((FunctionType*)(se->getType()))->getRetType() ==TypeSystem::voidType) {
                new RetInstruction(nullptr, *block);
            }
        }
        
    }
}

void BinaryExpr::genCode()
{
    //printf("binary\n");
    //得到正在处理的基本快
    BasicBlock *bb = builder->getInsertBB();
    Function *func = bb->getParent();
    if (op == AND)
    {
        //printf("and\n");
        BasicBlock *trueBB = new BasicBlock(func);  // if the result of lhs is true, jump to the trueBB.
        br_need=1;
        if(expr1->is_single)
            and_or=true;
        
        expr1->genCode();
        and_or=false;
        backPatch(expr1->trueList(), trueBB);
    //换一个基本快继续处理
        builder->setInsertBB(trueBB);               // set the insert point to the trueBB so that intructions generated by expr2 will be inserted into it.
        
        if(expr2->is_single)
            and_or=true;
        expr2->genCode();
        and_or=false;
        true_list = expr2->trueList();
        false_list = merge(expr1->falseList(), expr2->falseList());
        //printf("and\n");
    }
    else if(op == OR)
    {
        // Todo
        ///按照上面的照猫画虎画出流程图书写代码即可
        BasicBlock* falseBB =new BasicBlock(func);
        br_need=1;
        if(expr1->is_single)
            and_or=true;
        
        expr1->genCode();
        and_or=false;
        backPatch(expr1->falseList(),falseBB);
        builder->setInsertBB(falseBB);
        if(expr2->is_single)
            and_or=true;
        expr2->genCode();
        and_or=false;
        false_list = expr2->falseList();
        true_list=merge(expr1->trueList(),expr2->trueList());
    }
    else if(op >= LESS && op <= NOTEQUAL)
    {
        // Todo
        //照着下面的照猫画虎
        br_need--;
        expr1->genCode();
        expr2->genCode();
        br_need++;
        Operand *src1 = type_cast(TypeSystem::intType,expr1->getOperand());
        Operand *src2 = type_cast(TypeSystem::intType,expr2->getOperand());
        switch (op) {
            case LESS:
                op = CmpInstruction::L;
                break;
            case LESSEQUAL:
                op = CmpInstruction::LE;
                break;
            case GREATER:
                op = CmpInstruction::G;
                break;
            case GREATEREQUAL:
                op = CmpInstruction::GE;
                break;
            case EQUAL:
                op = CmpInstruction::E;
                break;
            case NOTEQUAL:
                op = CmpInstruction::NE;
                break;
        }
        new CmpInstruction(op, dst, src1, src2, bb);
        if(br_need>0){
            BasicBlock *truebb, *falsebb, *tempbb;
            truebb = new BasicBlock(func);
            falsebb = new BasicBlock(func);
            tempbb = new BasicBlock(func);

            true_list.push_back(new CondBrInstruction(truebb, tempbb, dst, bb));
            false_list.push_back(new UncondBrInstruction(falsebb, tempbb));
        }
    }
    else if(op >= ADD && op <= MOD)
    {
    //增加运算种类
        expr1->genCode();
        expr2->genCode();
        Operand *src1 = type_cast(TypeSystem::intType,expr1->getOperand());
        Operand *src2 = type_cast(TypeSystem::intType,expr2->getOperand());
        int opcode;
        switch (op)
        {
        case ADD:
            opcode = BinaryInstruction::ADD;
            break;
        case SUB:
            opcode = BinaryInstruction::SUB;
            break;
        case MUL:
            opcode = BinaryInstruction::MUL;
            break;
        case DIV:
            opcode = BinaryInstruction::DIV;
            break;
        case MOD:
            opcode = BinaryInstruction::MOD;
            break;
        }
        new BinaryInstruction(opcode, dst, src1, src2, bb);
    }
}

void Constant::genCode()
{
    //printf("const\n");
    // we don't need to generate code.
}

void Id::genCode()
{
    //printf("Id\n");
    BasicBlock *bb = builder->getInsertBB();
    Function*func = builder->getInsertBB()->getParent();
    Operand *addr = dynamic_cast<IdentifierSymbolEntry*>(symbolEntry)->getAddr();
    //std::cout<<addr->toStr()<<"  ";
    new LoadInstruction(dst, addr, bb);
    
    //if(i&&j)
    Operand* temp=new Operand(new TemporarySymbolEntry(TypeSystem::boolType, SymbolTable::getLabel()));
    if(and_or){
        new CmpInstruction(CmpInstruction::NE, temp, dst, new Operand(new ConstantSymbolEntry(TypeSystem::intType, 0)), bb);
        if(br_need>0){
            BasicBlock *truebb, *falsebb, *tempbb;
            truebb = new BasicBlock(func);
            falsebb = new BasicBlock(func);
            tempbb = new BasicBlock(func);

            true_list.push_back(new CondBrInstruction(truebb, tempbb, temp, bb));
            false_list.push_back(new UncondBrInstruction(falsebb, tempbb));
        }
    }
}

void IfStmt::genCode()
{
    //printf("if stmt\n");
    Function *func;
    BasicBlock *then_bb, *end_bb;

    func = builder->getInsertBB()->getParent();
    then_bb = new BasicBlock(func);
    end_bb = new BasicBlock(func);
    br_need=1;
    if (cond->getType()->isInt())
        and_or=true;         
    cond->genCode();
    and_or=false;
    backPatch(cond->trueList(), then_bb);
    backPatch(cond->falseList(), end_bb);

    builder->setInsertBB(then_bb);
    thenStmt->genCode();
    then_bb = builder->getInsertBB();
    new UncondBrInstruction(end_bb, then_bb);

    builder->setInsertBB(end_bb);
}

void IfElseStmt::genCode()
{
    //printf("if else\n");
    // Todo
    Function* func;
    BasicBlock *then_bb, *else_bb, *end_bb /*, *bb*/;
    // bb = builder->getInsertBB();
    func = builder->getInsertBB()->getParent();
    then_bb = new BasicBlock(func);
    else_bb = new BasicBlock(func);
    end_bb = new BasicBlock(func);
    br_need=1;
    if (cond->getOperand()->getType()->isInt())
        and_or=true;         
    cond->genCode();
    and_or=false;
    br_need=0;
    // Operand* IfElsecond = cond->getOperand();
    backPatch(cond->trueList(), then_bb);
    backPatch(cond->falseList(), else_bb);

    // new CondBrInstruction(then_bb,else_bb,IfElsecond,bb);

    builder->setInsertBB(then_bb);
    thenStmt->genCode();
    then_bb = builder->getInsertBB();
    new UncondBrInstruction(end_bb, then_bb);

    builder->setInsertBB(else_bb);
    elseStmt->genCode();
    else_bb = builder->getInsertBB();
    new UncondBrInstruction(end_bb, else_bb);

    builder->setInsertBB(end_bb);
}

void CompoundStmt::genCode()
{
    // Todo
    //printf("compound\n");
    if (stmt)
        stmt->genCode();
}

void SeqNode::genCode()
{
    //printf("seq node\n");
    // Todo
    stmt1->genCode();
    stmt2->genCode();
}

void DeclStmt::genCode()
{
    //printf("decl stmt\n");
    IdentifierSymbolEntry *se = dynamic_cast<IdentifierSymbolEntry *>(id->getSymbolEntry());
    //如果该变量为全局变量，则其addr为指针，指向sid的se
    if(se->isGlobal())
    {
        Operand *addr;
        SymbolEntry *addr_se;
        addr_se = new IdentifierSymbolEntry(*se);
        addr_se->setType(new PointerType(se->getType()));
        addr = new Operand(addr_se);
        se->setAddr(addr);
        unit.insertGlobal(se);
    }
    else if(se->isLocal()|| se->isParam())
    {
        Function *func = builder->getInsertBB()->getParent();
        BasicBlock *entry = func->getEntry();
        Instruction *alloca;
        Operand *addr;
        SymbolEntry *addr_se;
        Type *type;
        type = new PointerType(se->getType());
        addr_se = new TemporarySymbolEntry(type, SymbolTable::getLabel());
        addr = new Operand(addr_se);
        alloca = new AllocaInstruction(addr, se);                   // allocate space for local id in function stack.
        entry->insertFront(alloca);                                 // allocate instructions should be inserted into the begin of the entry block.
        Operand* temp;
        if (se->isParam()){
            temp = se->getAddr(); 
            //printf("try to catch addr");
        }                              
        se->setAddr(addr); 
        if (expr) {
            BasicBlock* bb = builder->getInsertBB();
            expr->genCode();
            Operand* src = type_cast(se->getType(),expr->getOperand());
            new StoreInstruction(addr, src, bb);
        }
        if (se->isParam()) {
            BasicBlock* bb = builder->getInsertBB();
            if(addr==nullptr)
                printf("addr\n");
            else if(temp==nullptr)
                printf("temp\n");
            else if(bb==nullptr)
                printf("bb\n");
            new StoreInstruction(addr, temp, bb);
            //printf("stored\n");
        }                                        
    }
    if (this->getNext()) {
        this->getNext()->genCode();
    }
}

void ReturnStmt::genCode()
{
    //printf("return\n");
    // Todo
    BasicBlock* bb = builder->getInsertBB();
    Operand* src = nullptr;
    if (retValue) {
        retValue->genCode();
        src = retValue->getOperand();
    }
    new RetInstruction(src, bb);
}

void ExprNode::genCode()
{
    // Todo
    //printf("expr\n");
}

//下面还需要补充一些东西
void ExprStmt::genCode(){
    //printf("expr stmt\n");
    expr->genCode();
}
void ContinueStmt::genCode() {
    // Todo

    Function* func = builder->getInsertBB()->getParent();
    BasicBlock* bb = builder->getInsertBB();
    new UncondBrInstruction(((WhileStmt*)tar_while)->get_cond_bb(), bb);
    BasicBlock* continue_next_bb = new BasicBlock(func);
    builder->setInsertBB(continue_next_bb);
}
void BreakStmt::genCode() {
    // Todo
    Function* func = builder->getInsertBB()->getParent();
    BasicBlock* bb = builder->getInsertBB();
    new UncondBrInstruction(((WhileStmt*)tar_while)->get_end_bb(), bb);
    BasicBlock* break_next_bb = new BasicBlock(func);
    builder->setInsertBB(break_next_bb);
}
void WhileStmt::genCode() {
    Function* func;
    BasicBlock *cond_bb, *while_bb, *end_bb, *bb;
    bb = builder->getInsertBB();
    func = builder->getInsertBB()->getParent();
    cond_bb = new BasicBlock(func);
    while_bb = new BasicBlock(func);
    end_bb = new BasicBlock(func);

    this->cond_bb = cond_bb;
    this->end_bb = end_bb;

    new UncondBrInstruction(cond_bb, bb);

    builder->setInsertBB(cond_bb);
    br_need=1;
    if (cond->getType()->isInt())
        and_or=true;         
    cond->genCode();
    and_or=false;
    backPatch(cond->trueList(), while_bb);
    backPatch(cond->falseList(), end_bb);
    // Operand* condoperand= cond->getOperand();
    // new CondBrInstruction(while_bb,end_bb,condoperand,cond_bb);

    builder->setInsertBB(while_bb);
    stmt->genCode();

    while_bb = builder->getInsertBB();
    new UncondBrInstruction(cond_bb, while_bb);

    builder->setInsertBB(end_bb);
}
void BlankStmt::genCode() {
    // Todo
}

void CallExpr::genCode() {
    std::vector<Operand*> operands;
    ExprNode* temp = param;
    //if(func()&&)
    Operand* dst1=new Operand(new TemporarySymbolEntry(TypeSystem::boolType, SymbolTable::getLabel()));
    int i=1;
    while (temp) {
        temp->genCode();
        operands.push_back(temp->getOperand());
        temp = ((ExprNode*)temp->getNext());
        //printf("%d\n",i);
        i++;
    }
    BasicBlock* bb = builder->getInsertBB();
    Function* func=bb->getParent();
    new CallInstruction(dst, symbolEntry, operands, bb);
    if(and_or&&dst->getType()->isInt()){
        new CmpInstruction(CmpInstruction::NE, dst1, dst, new Operand(new ConstantSymbolEntry(TypeSystem::intType, 0)), bb);
        BasicBlock *truebb, *falsebb, *tempbb;
        truebb = new BasicBlock(func);
        falsebb = new BasicBlock(func);
        tempbb = new BasicBlock(func);
        true_list.push_back(new CondBrInstruction(truebb, tempbb, dst1, bb));
        false_list.push_back(new UncondBrInstruction(falsebb, tempbb));
        //printf("6\n");
    }

}
void UnaryExpr::genCode() {
    // Todo
    BasicBlock* bb = builder->getInsertBB();
    Function *func = bb->getParent();
    Operand* src = expr->getOperand();
    
    
    Operand* src1,*src2;
    if (op == NOT) {
        br_need--;
        expr->genCode();
        br_need++;
        if (expr->getOperand()->getType()->isInt()) 
            src1=type_cast(TypeSystem::boolType,src);
        else
            src1=src;
        new XorInstruction(dst,src1, bb);
        
    } 
    else if (op == SUB) {
        expr->genCode();
        src1 = new Operand(new ConstantSymbolEntry(TypeSystem::intType, 0));
        if (expr->getOperand()->getType()->isBool()) {
             src2 = type_cast(TypeSystem::intType,src);
             //printf("666\n");
        }   
        else
            src2=src;
        new BinaryInstruction(BinaryInstruction::SUB, dst, src1, src2, bb);
    }
    if(br_need>0){
        if(getOperand()->getType()->isInt()){
            dst=type_cast(TypeSystem::boolType,dst);
        }
            BasicBlock *truebb, *falsebb, *tempbb;
            truebb = new BasicBlock(func);
            falsebb = new BasicBlock(func);
            tempbb = new BasicBlock(func);
            true_list.push_back(new CondBrInstruction(truebb, tempbb, dst, bb));
            false_list.push_back(new UncondBrInstruction(falsebb, tempbb));
    }
}


void AssignStmt::genCode() {
    BasicBlock* bb = builder->getInsertBB();
    expr->genCode();
    Operand* addr;
    Operand *src;
    addr = ((IdentifierSymbolEntry*)(lval->getSymbolEntry()))->getAddr();
    src = type_cast(((PointerType*)(addr->getType()))->getPT(), expr->getOperand());
    /***
     * We haven't implemented array yet, the lval can only be ID. So we just
     * store the result of the `expr` to the addr of the id. If you want to
     * implement array, you have to caculate the address first and then store
     * the result into it.
     */
    new StoreInstruction(addr, src, bb);
}


